package com.fancy.application.sys.datasource.config;

import com.fancy.application.sys.datasource.Exception.DataSourceNotFoundException;
import com.fancy.application.sys.datasource.entity.SysDataSourceMain;
import com.fancy.application.sys.datasource.event.DynamicDataSourceRegisterEvent;
import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Log4j2
@RefreshDependency
@Component("dataSourceConfig")
public class DataSourceConfig implements ApplicationContextAware, BeanFactoryAware {


    private ConfigurableApplicationContext ctx;
    private DefaultListableBeanFactory beanFactory;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = (DefaultListableBeanFactory) beanFactory;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.ctx = (ConfigurableApplicationContext) ctx;
    }


    public DataSource getDataSource(String fdKey){
        Map<String,DataSource> dataSourceMap = beanFactory.getBeansOfType(DataSource.class);
        if(!dataSourceMap.containsKey(fdKey)){
            log.error("无法找到标识为{}的数据源",fdKey);
            throw new DataSourceNotFoundException("无法找到标识为{"+fdKey+"}的数据源");
        }
        return dataSourceMap.get(fdKey);

    }

    public List<String> getDataSources(){
        Map<String,DataSource> dataSourceMap = beanFactory.getBeansOfType(DataSource.class);
        List<String> keys = new ArrayList<>();
        dataSourceMap.forEach((k,v)->{
            keys.add(k);
        });
        return keys;

    }

    public DataSource registerDataSource(SysDataSourceMain sysDataSourceMain) {
        boolean createFlag = true;
        HikariDataSource dataSource = new HikariDataSource();
        try {
            dataSource.setDriverClassName(sysDataSourceMain.getFdDbDriver());
            dataSource.setJdbcUrl(sysDataSourceMain.getFdDbUrl());
            dataSource.setUsername(sysDataSourceMain.getFdUsername());
            dataSource.setPassword(sysDataSourceMain.getFdPassword());
            dataSource.getConnection();
        }catch (SQLException e){
            log.warn("数据源{}--{}创建失败",sysDataSourceMain.getFdName(),sysDataSourceMain.getFdKey());
            createFlag = false;
            e.printStackTrace();
        }
        if(createFlag){
            beanFactory.registerSingleton(sysDataSourceMain.getFdKey(), dataSource);
            //ctx.publishEvent(new DynamicDataSourceRegisterEvent(ctx));
            log.info("数据源{}--{}创建完成",sysDataSourceMain.getFdName(),sysDataSourceMain.getFdKey());
        }

        return dataSource;
    }

    public List<HikariDataSource> BatchRegisterDataSource(List<SysDataSourceMain> sysDataSourceMains) {
        List<HikariDataSource> dataSourceList = new ArrayList<>();
        sysDataSourceMains.forEach(sysDataSourceMain -> {
            boolean createFlag = true;
            HikariDataSource dataSource = new HikariDataSource();
            try {
                dataSource.setDriverClassName(sysDataSourceMain.getFdDbDriver());
                dataSource.setJdbcUrl(sysDataSourceMain.getFdDbUrl());
                dataSource.setUsername(sysDataSourceMain.getFdUsername());
                dataSource.setPassword(sysDataSourceMain.getFdPassword());
                dataSource.getConnection();
            }catch (SQLException e){
                log.warn("数据源{}--{}创建失败",sysDataSourceMain.getFdName(),sysDataSourceMain.getFdKey());
                createFlag = false;
                e.printStackTrace();
            }
            if(createFlag){
                beanFactory.registerSingleton(sysDataSourceMain.getFdKey(), dataSource);
                dataSourceList.add(dataSource);
                log.info("数据源{}--{}创建完成",sysDataSourceMain.getFdName(),sysDataSourceMain.getFdKey());
            }
        });

        //ctx.publishEvent(new DynamicDataSourceRegisterEvent(ctx));
        return dataSourceList;
    }
}
